﻿#region MIT License
/*
 *  Copyright (c) 2010 Nathan Palmer
 *  http://www.nathanpalmer.com/
 * 
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 * 
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 * 
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */
#endregion

using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using NLog;
using Quartz;

namespace SimpleScheduler.Core.Common
{
    public static class ExtensionMethods
    {
        /// <summary>Serialises an object of type T in to an xml string</summary>
        /// <typeparam name="T">Any class type</typeparam>
        /// <param name="objectToSerialise">Object to serialise</param>
        /// <returns>A string that represents Xml, empty oterwise</returns>
        public static string XmlSerialize<T>(this T objectToSerialise) where T : class
        {
            var serialiser = new XmlSerializer(typeof(T));
            string xml;
            using (var memStream = new MemoryStream())
            {
                // Parameterize this                    
                XmlWriterSettings xmlSettings = new XmlWriterSettings();
                xmlSettings.OmitXmlDeclaration = true;
                xmlSettings.Indent = true;

                //using (var xmlWriter = new XmlTextWriter(memStream, Encoding.UTF8))
                using (var xmlWriter = XmlWriter.Create(memStream, xmlSettings))
                {
                    XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces();
                    xmlNamespace.Add(string.Empty, string.Empty);

                    serialiser.Serialize(xmlWriter, objectToSerialise, xmlNamespace);
                    xml = Encoding.UTF8.GetString(memStream.GetBuffer());
                }
            }

            xml = xml.Substring(xml.IndexOf(Convert.ToChar(60)));
            xml = xml.Substring(0, (xml.LastIndexOf(Convert.ToChar(62)) + 1));
            return xml;
        }

        /// <summary>Deserialises an xml string in to an object of Type T</summary>
        /// <typeparam name="T">Any class type</typeparam>
        /// <param name="xml">Xml as string to deserialise from</param>
        /// <returns>A new object of type T is successful, null if failed</returns>
        public static T XmlDeserialize<T>(this string xml) where T : class
        {
            var serialiser = new XmlSerializer(typeof(T));
            T newObject;

            

            using (var stringReader = new StringReader(xml))
            {
                using (var xmlReader = new XmlTextReader(stringReader))
                {
                    try
                    {
                        newObject = serialiser.Deserialize(xmlReader) as T;
                    }
                    catch (InvalidOperationException) // String passed is not Xml, return null
                    {
                        //return null;
                        throw;
                    }

                }
            }

           

            return newObject;
        }

        /// <summary>Deserialises an xml string in to an object of Type T</summary>
        /// <typeparam name="T">Any class type</typeparam>
        /// <param name="xml">Xml as string to deserialise from</param>
        /// <returns>A new object of type T is successful, null if failed</returns>
        public static object XmlDeserialize(this string xml, Type type)
        {
            var serialiser = new XmlSerializer(type);
            object newObject;

            using (var stringReader = new StringReader(xml))
            {
                using (var xmlReader = new XmlTextReader(stringReader))
                {
                    try
                    {
                        XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces();
                        xmlNamespace.Add(string.Empty, string.Empty);
                        newObject = serialiser.Deserialize(xmlReader);
                    }
                    catch (InvalidOperationException) // String passed is not Xml, return null
                    {
                        //return null;
                        throw;
                    }
                }
            }

            return newObject;
        }

        public static LogEventInfo PrepareMessage(this JobExecutionContext context, LogLevel Level, string Message)
        {
            LogEventInfo logInfo = new LogEventInfo();
            logInfo.Context["job-group"] = context.JobDetail.Group;
            logInfo.Context["job-name"] = context.JobDetail.Name;
            logInfo.Level = Level;
            logInfo.TimeStamp = DateTime.Now;
            logInfo.Message = Message;

            return logInfo;
        }
    }
}